home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cdrecord-1.8.1 / lib / raisecond.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-11  |  4.2 KB  |  158 lines

  1. /* @(#)raisecond.c    1.11 99/09/11 Copyright 1985 J. Schilling */
  2. /*
  3.  *    raise a condition (software signal)
  4.  */
  5. /*
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2, or (at your option)
  9.  * any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; see the file COPYING.  If not, write to
  18.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20. /*
  21.  *    Check for installed condition handlers.
  22.  *    If a handler is found, the function is called with the appropriate args.
  23.  *    If no handler is found or no handler signals success,
  24.  *    the program will be aborted.
  25.  *
  26.  *    Copyright (c) 1985 J. Schilling
  27.  */
  28. #include <mconfig.h>
  29. #include <stdio.h>
  30. #include <standard.h>
  31. #include <sigblk.h>
  32. #include <unixstd.h>
  33. #include <stdxlib.h>
  34. #include <strdefs.h>
  35. #include <avoffset.h>
  36.  
  37. #if    !defined(AV_OFFSET) || !defined(FP_INDIR)
  38. #    ifdef    HAVE_SCANSTACK
  39. #    undef    HAVE_SCANSTACK
  40. #    endif
  41. #endif
  42. #ifdef    NO_SCANSTACK
  43. #    ifdef    HAVE_SCANSTACK
  44. #    undef    HAVE_SCANSTACK
  45. #    endif
  46. #endif
  47.  
  48. /*
  49.  * Macros to print to stderr without stdio, to avoid screwing up.
  50.  */
  51. #ifndef    STDERR_FILENO
  52. #define    STDERR_FILENO    2
  53. #endif
  54. #define    eprints(a)    (void)write(STDERR_FILENO, (a), sizeof(a)-1)
  55. #define    eprintl(a)    (void)write(STDERR_FILENO, (a), strlen(a))
  56.  
  57. #define    is_even(p)    ((((long)(p)) & 1) == 0)
  58. #define    even(p)        (((long)(p)) & ~1L)
  59. #ifdef    __future__
  60. #define    even(p)        (((long)(p)) - 1)/* will this work with 64 bit ?? */
  61. #endif
  62.  
  63.  
  64. LOCAL    void raiseabort  __PR((const char *));
  65.  
  66. #ifdef    HAVE_SCANSTACK
  67.  
  68. #include <stkframe.h>
  69.  
  70. LOCAL    BOOL framehandle __PR((SIGBLK *, const char *, const char *, long));
  71.  
  72. /*
  73.  *    Loop through the chain of procedure frames on the stack.
  74.  *
  75.  *    Frame pointers normally have even values.
  76.  *    Frame pointers of procedures with an installed handler are marked odd.
  77.  *    The even base value, in this case actually points to a SIGBLK which
  78.  *    holds the saved "real" frame pointer.
  79.  *    The SIGBLK mentioned above may me the start of a chain of SIGBLK's,
  80.  *    containing different handlers.
  81.  */
  82. void raisecond(signame, arg2)
  83.     const char    *signame;
  84.     long        arg2;
  85. {
  86.     register struct frame *fp = (struct frame *)getfp();
  87.  
  88.     for(; fp; fp = (struct frame *)fp->fr_savfp) {
  89.         if (is_even(fp))
  90.             continue;
  91.         fp = (struct frame *)even(fp);    /* really is (SIGBLK *) */
  92.  
  93.         if (framehandle((SIGBLK *)fp, signame, signame, arg2))
  94.             return;
  95.         else if (framehandle((SIGBLK *)fp, "any_other", signame, arg2))
  96.             return;
  97.         fp = (struct frame *)((SIGBLK *)fp)->sb_savfp;
  98.     }
  99.     /*
  100.      * No matching handler that signals success found.
  101.      * Print error message and abort.
  102.      */
  103.     raiseabort(signame);
  104.     /* NOTREACHED */
  105. }
  106.  
  107. /*
  108.  *    Loop through the handler chain for a procedure frame.
  109.  *
  110.  *    If no handler with matching name is found, return FALSE,
  111.  *    otherwise the first handler with matching name is called.
  112.  *    The return value in the latter case depends on the called function.
  113.  */
  114. LOCAL BOOL framehandle(sp, handlename, signame, arg2)
  115.     register SIGBLK *sp;
  116.     const char    *handlename;
  117.     const char    *signame;
  118.     long        arg2;
  119. {
  120.     for(; sp; sp = sp->sb_signext) {
  121.         if (streql(sp->sb_signame, handlename)) {
  122.             if (sp->sb_sigfun == NULL) {    /* deactivated */
  123.                 return (FALSE);
  124.             } else {
  125.                 return (*sp->sb_sigfun)(signame,
  126.                             sp->sb_sigarg, arg2);
  127.             }
  128.         }
  129.     }
  130.     return (FALSE);
  131. }
  132.  
  133. #else    /* HAVE_SCANSTACK */
  134.  
  135. void raisecond(signame, arg2)
  136.     const char    *signame;
  137.     long        arg2;
  138. {
  139.     /*
  140.      * Print error message and abort.
  141.      */
  142.     raiseabort(signame);
  143.     /* NOTREACHED */
  144. }
  145.  
  146. #endif    /* HAVE_SCANSTACK */
  147.  
  148. LOCAL void raiseabort(signame)
  149.     const    char    *signame;
  150. {
  151.     eprints("Condition not caught: "); eprintl(signame); eprints(".\n");
  152. #ifndef    HAVE_SCANSTACK
  153.     eprints("Raisecond: not implemented.\n");
  154. #endif
  155.     abort();
  156.     /* NOTREACHED */
  157. }
  158.